# 位置参数
# 我们先写一个计算x2的函数：


def power(x):
    return x * x


print(power(5))


# 如果我们要计算x3怎么办？可以再定义一个power3函数，但是如果要计算x4、x5……怎么办？我们不可能定义无限多个函数。
def power(x, n=2):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s


print(power(5, 3))
# 加入默认参数
# ，有几点要注意：

# 一是必选参数在前，默认参数在后，否则Python的解释器会报错（思考一下为什么默认参数不能放在必选参数前面）；

# 二是如何设置默认参数。

# 当函数有多个参数时，把变化大的参数放前面，变化小的参数放后面。变化小的参数就可以作为默认参数。

# 使用默认参数有什么好处？最大的好处是能降低调用函数的难度。
print(power(5))


# 填入学生信息，加入默认参数
def login(name, age, gnder='male', city='wuhan'):
    print('name ' + name, 'age ' + str(age), 'gnder ' + gnder, 'city ' + city)


login('张飞', 90)
login('貂蝉', 30, 'female', 'hebei')


# 默认参数很有用，但使用不当，也会掉坑里。默认参数有个最大的坑，不设置为空，每次调用都会叠加
def add(l=[]):
    l.append('END')
    return l


print(add())
print(add())
print(add())


# 修改....
def add2(l=None):
    if l is None:
        l = []
    l.append('END')
    return l


print(add2())
print(add2())
print(add2())


# 可变参数 计算1*1+2*2+3*3+.........+n*n
def multiply(*nums):
    sum = 0
    for x in nums:
        sum = sum + x * x
    return sum


print(multiply(1, 2, 3))
# 元祖转化为Python允许你在list或tuple前面加一个*号，把list或tuple的元素变成可变参数传进去：
nums = [1, 2, 3, 4, 5]
print(multiply(*nums))


# 关键字参数 [可传可不传]
# 可变参数允许你传入0个或任意个参数，这些可变参数在函数调用时自动组装为一个tuple。
# 而关键字参数允许你传入0个或任意个含参数名的参数，这些关键字参数在函数内部自动组装为一个dict。请看示例：
def regiest(name, age, **kb):
    print('name ', name, 'age ', age, 'other ', kb)


regiest('kun', 25)
regiest('kun', 25, city='beijing')
regiest('kun', 25, city='beijing', sex='female')
# 试想你正在做一个用户注册的功能，除了用户名和年龄是必填项外，其他都是可选项，利用关键字参数来定义这个函数就能满足注册的需求。
map = {'city': 'wuhan', 'sex': 'male'}
regiest('lifei', 60, city=map['city'], sex=map['sex'])


# 命名关键字参数
# 对于关键字参数，函数的调用者可以传入任意不受限制的关键字参数。至于到底传入了哪些，就需要在函数内部通过kw检查。
def person(name, age, *, city, job):
    print(name, age, city, job)


person('Jack', 24, city='Beijing', job='Engineer')
